<!DOCTYPE HTML>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>波浪</title>
</head>
<style>
  * {
    margin: 0;
    padding: 0;
  }

  html, body {
    height: 100%;
    width: 100%;
  }

  canvas {
    pointer-events: none;
  }
</style>

<body>
  <canvas id="canvas">

    <!-- 程俊彰修改自麒麟系统官网 -->

  </canvas>
  <script>
    (function () {
      var pi = Math.PI;
      var pi2 = 2 * Math.PI;

      this.Waves = function (holder, options) {
        var Waves = this;

        Waves.options = extend(options || {}, {
          resize: false,
          rotation: 45,
          waves: 5,
          width: 100,
          hue: [11, 14],
          amplitude: 0.5,
          background: true,
          preload: true,
          speed: [0.004, 0.008],
          debug: false,
          fps: false,
        });

        Waves.waves = [];

        Waves.canvas = document.getElementById('canvas');
        Waves.canvas.width = window.innerWidth;
        Waves.canvas.height = window.innerHeight;
        Waves.ctx = Waves.canvas.getContext('2d');

        Waves.hue = Waves.options.hue[0];
        Waves.hueFw = true;
        Waves.stats = new Stats();

        Waves.resize();
        Waves.init(Waves.options.preload);

        if (Waves.options.resize)
          window.addEventListener('resize', function () {
            Waves.resize();
          }, false);

      };

      Waves.prototype.init = function (preload) {
        var Waves = this;
        var options = Waves.options;

        for (var i = 0; i < options.waves; i++)
          Waves.waves[i] = new Wave(Waves);

        if (preload) Waves.preload();
      };

      Waves.prototype.preload = function () {
        var Waves = this;
        var options = Waves.options;

        for (var i = 0; i < options.waves; i++) {
          Waves.updateColor();
          for (var j = 0; j < options.width; j++) {
            Waves.waves[i].update();
          }
        }
      };

      Waves.prototype.render = function () {
        var Waves = this;
        var ctx = Waves.ctx;
        var options = Waves.options;

        Waves.updateColor();
        Waves.clear();

        if (Waves.options.debug) {
          ctx.beginPath();
          ctx.strokeStyle = '#f00';
          ctx.arc(Waves.centerX, Waves.centerY, Waves.radius, 0, pi2);
          ctx.stroke();
        }

        if (Waves.options.background) {
          Waves.background();
        }

        each(Waves.waves, function (wave, i) {
          wave.update();
          wave.draw();
        });
      };

      Waves.prototype.animate = function () {
        var Waves = this;

        Waves.render();

        if (Waves.options.fps) {
          Waves.stats.log();
          Waves.ctx.font = '12px Arial';
          Waves.ctx.fillStyle = '#fff';
          Waves.ctx.fillText(Waves.stats.fps() + ' FPS', 10, 22);
        }

        window.requestAnimationFrame(Waves.animate.bind(Waves));
      };

      Waves.prototype.clear = function () {
        var Waves = this;
        Waves.ctx.clearRect(0, 0, Waves.width, Waves.height);
      };

      Waves.prototype.background = function () {
        var Waves = this;
        var ctx = Waves.ctx;

        var gradient = Waves.ctx.createLinearGradient(0, 0, 0, Waves.height);
        gradient.addColorStop(0, '#deebfb');
        gradient.addColorStop(0.9, Waves.color);

        ctx.fillStyle = gradient;
        ctx.fillRect(0, 0, Waves.width, Waves.height);
      };

      Waves.prototype.resize = function () {
        var Waves = this;
        var width = Waves.canvas.offsetWidth;
        var height = Waves.canvas.offsetHeight;
        Waves.scale = window.devicePixelRatio || 1;
        Waves.width = width * Waves.scale;
        Waves.height = height * Waves.scale;
        Waves.canvas.width = Waves.width;
        Waves.canvas.height = Waves.height;
        Waves.canvas.style.width = width + 'px';
        Waves.canvas.style.height = height + 'px';
        Waves.radius = Math.sqrt(Math.pow(Waves.width, 2) + Math.pow(Waves.height, 2)) / 2;
        Waves.centerX = Waves.width / 2;
        Waves.centerY = Waves.height / 2;
        //Waves.radius /= 2; // REMOVE FOR FULLSREEN
      };

      Waves.prototype.updateColor = function () {
        var Waves = this;

        Waves.hue += (Waves.hueFw) ? 0.01 : -0.01;

        if (Waves.hue > Waves.options.hue[1] && Waves.hueFw) {
          Waves.hue = Waves.options.hue[1];
          Waves.Waves = false;
        } else if (Waves.hue < Waves.options.hue[0] && !Waves.hueFw) {
          Waves.hue = Waves.options.hue[0];
          Waves.Waves = true;
        }

        var a = Math.floor(127 * Math.sin(0.3 * Waves.hue + 0) + 128);
        var b = Math.floor(127 * Math.sin(0.3 * Waves.hue + 2) + 128);
        var c = Math.floor(127 * Math.sin(0.3 * Waves.hue + 4) + 128);

        Waves.color = 'rgba(' + a + ',' + b + ',' + c + ', 0.1)';
      };

      function Wave(Waves) {
        var Wave = this;
        var speed = Waves.options.speed;

        Wave.Waves = Waves;
        Wave.Lines = [];

        Wave.angle = [
          rnd(pi2),
          rnd(pi2),
          rnd(pi2),
          rnd(pi2)
        ];

        Wave.speed = [
          rnd(speed[0], speed[1]) * rnd_sign(),
          rnd(speed[0], speed[1]) * rnd_sign(),
          rnd(speed[0], speed[1]) * rnd_sign(),
          rnd(speed[0], speed[1]) * rnd_sign(),
        ];

        return Wave;
      }

      Wave.prototype.update = function () {
        var Wave = this;
        var Lines = Wave.Lines;
        var color = Wave.Waves.color;

        Lines.push(new Line(Wave, color));

        if (Lines.length > Wave.Waves.options.width) {
          Lines.shift();
        }
      };

      Wave.prototype.draw = function () {
        var Wave = this;
        var Waves = Wave.Waves;

        var ctx = Waves.ctx;
        var radius = Waves.radius;
        var radius3 = radius / 3;
        var x = Waves.centerX;
        var y = Waves.centerY;
        var rotation = dtr(Waves.options.rotation);
        var amplitude = Waves.options.amplitude;
        var debug = Waves.options.debug;

        var Lines = Wave.Lines;

        each(Lines, function (line, i) {
          if (debug && i > 0) return;

          var angle = line.angle;

          var x1 = x - radius * Math.cos(angle[0] * amplitude + rotation);
          var y1 = y - radius * Math.sin(angle[0] * amplitude + rotation);
          var x2 = x + radius * Math.cos(angle[3] * amplitude + rotation);
          var y2 = y + radius * Math.sin(angle[3] * amplitude + rotation);
          var cpx1 = x - radius3 * Math.cos(angle[1] * amplitude * 2);
          var cpy1 = y - radius3 * Math.sin(angle[1] * amplitude * 2);
          var cpx2 = x + radius3 * Math.cos(angle[2] * amplitude * 2);
          var cpy2 = y + radius3 * Math.sin(angle[2] * amplitude * 2);

          ctx.strokeStyle = (debug) ? '#fff' : line.color;

          ctx.beginPath();
          ctx.moveTo(x1, y1);
          ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x2, y2);
          ctx.stroke();

          if (debug) {
            ctx.strokeStyle = '#fff';
            ctx.globalAlpha = 0.3;

            ctx.beginPath();
            ctx.moveTo(x1, y1);
            ctx.lineTo(cpx1, cpy1);
            ctx.stroke();
            ctx.beginPath();
            ctx.moveTo(x2, y2);
            ctx.lineTo(cpx2, cpy2);
            ctx.stroke();

            ctx.globalAlpha = 1;
          }
        });
      };

      function Line(Wave, color) {
        var Line = this;

        var angle = Wave.angle;
        var speed = Wave.speed;

        Line.angle = [
          Math.sin(angle[0] += speed[0]),
          Math.sin(angle[1] += speed[1]),
          Math.sin(angle[2] += speed[2]),
          Math.sin(angle[3] += speed[3])
        ];

        Line.color = color;
      }

      function Stats() {
        this.data = [];
      }

      Stats.prototype.time = function () {
        return (performance || Date)
          .now();
      };

      Stats.prototype.log = function () {
        if (!this.last) {
          this.last = this.time();
          return 0;
        }

        this.new = this.time();
        this.delta = this.new - this.last;
        this.last = this.new;

        this.data.push(this.delta);
        if (this.data.length > 10)
          this.data.shift();
      };

      Stats.prototype.fps = function () {
        var fps = 0;
        each(this.data, function (data, i) {
          fps += data;
        });

        return Math.round(1000 / (fps / this.data.length));
      };

      function each(items, callback) {
        for (var i = 0; i < items.length; i++) {
          callback(items[i], i);
        }
      }

      function extend(options, defaults) {
        for (var key in options)
          if (defaults.hasOwnProperty(key))
            defaults[key] = options[key];
        return defaults;
      }

      function dtr(deg) {
        return deg * pi / 360;
      }

      function rtd(rad) {
        return rad * 360 / pi;
      }

      function diagonal_angle(w, h) {
        var a = Math.atan2(h, w) * 1.27325;
        return a;
      }

      function rnd(a, b) {
        if (arguments.length == 1)
          return Math.random() * a;
        return a + Math.random() * (b - a);
      }

      function rnd_sign() {
        return (Math.random() > 0.5) ? 1 : -1;
      }

    })();
    //如果改为true ，就会显示在屏幕上
    var waves = new Waves('#holder', {
      fps: false,
      waves: 3,
      width: 100,
    });

    waves.animate();
  </script>
</body>

</html>